package com.logistics.command.service;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.logistics.command.model.CarryingModel;
import com.logistics.command.model.DeliveryModel;
import com.logistics.command.model.PlaceModel;
import com.logistics.delivery.entity.model.DeliveryRow;
import com.logistics.dictionary.entity.model.DictionaryRow;
import com.logistics.dictionary.service.DictionaryService;
import com.logistics.heart.entity.model.HeartRow;
import com.logistics.heart.service.HeartService;
import com.logistics.map.entity.domain.MapComponents;
import com.logistics.map.service.MapComponentsService;
import com.logistics.qrcode.service.QrcodeService;
import com.logistics.socket.model.RequestTaskModel;
import com.logistics.socket.service.RequestSocketService;
import com.logistics.socket.service.ResponseSocketService;
import com.logistics.utils.constants.Constants;
import com.logistics.utils.constants.Message;
import com.logistics.utils.exception.MessageException;
import com.logistics.utils.message.Manager;
import com.logistics.utils.socket.EventData;
import com.logistics.utils.tool.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;


@Service
public class CommandService {

    @Autowired
    private RequestSocketService requestSocketService;

    @Autowired
    private HeartService heartService;

    @Autowired
    private MapComponentsService mapComponentsService;

    @Autowired
    private QrcodeService qrcodeService;

    @Autowired
    private DictionaryService dictionaryService;

    /**
     * 托盘搭载-指令
     * @param model
     */
    public void carrying(CarryingModel model) throws JsonProcessingException, MessageException {
        checkDevice(model.getAgvCode());
        String point = qrcodeService.valueByCode(model.getEndStation(), Constants.CODE_TYPE_LOCATION);
        requestSocketService.genAgvSchedulingTask(RequestTaskModel.build("4", model.getAgvCode(), point));
    }

    /**
     * 托盘放置-指令
     * @param model
     */
    public void place(PlaceModel model) throws JsonProcessingException, MessageException{
        checkDevice(model.getAgvCode());
        String point = qrcodeService.valueByCode(model.getEndStation(), Constants.CODE_TYPE_LOCATION);
        MapComponents result = mapComponentsService.getOne(new LambdaQueryWrapper<MapComponents>().eq(MapComponents::getLocation, point).
                eq(MapComponents::getClazz, Constants.COMPONENTS_TYPE_LOCATION));
        if(StringUtils.isNull(result)){
            throw new MessageException("不是有效的站点，请确认");
        }
        // 查找车间信息
        List<DictionaryRow> resultDictionary = dictionaryService.listByTypes("workshop");
        String externalCode = resultDictionary.get(0).getChildren().stream().
                filter(e -> StringUtils.isEquals(result.getWorkshop(), e.getCode()))
                .map(e -> e.getExternalCode()).collect(Collectors.joining());
        if(StringUtils.isNull(externalCode)){
            throw new MessageException("没有找到车间，不能完成托盘放置操作");
        }
        requestSocketService.genAgvSchedulingTask(RequestTaskModel.build("5", model.getAgvCode(), point));
        requestSocketService.genAgvSchedulingTask(RequestTaskModel.build("2", model.getAgvCode(), externalCode));
    }

    /**
     * 点到点
     * @param ip
     * @param station
     */
    public void pointToPoint(String ip, String station) throws JsonProcessingException, MessageException {
        if(StringUtils.isNull(ip)){
            throw new MessageException("车辆编号不能为空");
        }
        if(StringUtils.isNull(station)){
            throw new MessageException("位置不能为空");
        }
        requestSocketService.genAgvSchedulingTask(RequestTaskModel.build("2",ip, station));
    }

    /**
     * 发送任务
     * @throws JsonProcessingException
     * @throws MessageException
     */
    public void sendTask(String agv, DeliveryRow row) throws JsonProcessingException {
        requestSocketService.sendMessage(EventData.build("__task_scheduling",
                RequestTaskModel.build(row, agv)));
    }
    /**
     * 配送
     * @param model
     */
    @Transactional
    public void delivery(DeliveryModel model) throws JsonProcessingException, MessageException{
        checkDevice(model.getAgvCode());
        String location = mapComponentsService.getLocation(model.getSiteId());
        if(StringUtils.isNotNull(location)){
            ResponseSocketService.callBackMap.put(model.getAgvCode(), true);
            requestSocketService.genAgvSchedulingTask(RequestTaskModel.build("5", model.getAgvCode(), location));
        }
    }

    /**
     * 检查设备
     * @param ip
     * @throws MessageException
     */
    private void checkDevice(String ip) throws MessageException {
        HeartRow result = heartService.heartByIp(ip);
        if(StringUtils.isEquals(result.getConnectState(), Constants.CONNECTION_STATE_CLOSED)){
            throw new MessageException(Manager.getMessage(Message.MSG1017.getCode()));
        }
        if(!StringUtils.isEquals(result.getHandleState(), Constants.HANDLER_STATE_STANDBY)){
            throw new MessageException(Manager.getMessage(Message.MSG1018.getCode()));
        }
    }

}
